package service

import (
	"MyBlogv2/common/HttpCode"
	"MyBlogv2/common/models"
	"MyBlogv2/common/response"
	"fmt"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

// 查询结果结构
type QueryResult struct {
	Columns     []string                 `json:"columns"`
	Rows        []map[string]interface{} `json:"rows"`
	RowCount    int                      `json:"rowCount"`
	ExecuteTime int64                    `json:"executeTime"` // 毫秒
}

// 表结构信息
type TableStructure struct {
	Field   string      `json:"Field"`
	Type    string      `json:"Type"`
	Null    string      `json:"Null"`
	Key     string      `json:"Key"`
	Default interface{} `json:"Default"`
	Extra   string      `json:"Extra"`
	Comment string      `json:"Comment"`
}

// 数据库统计信息
type DatabaseStats struct {
	TableCount   int                `json:"tableCount"`
	TotalRows    int64              `json:"totalRows"`
	DatabaseSize string             `json:"databaseSize"`
	IndexSize    string             `json:"indexSize"`
	Tables       []TableDetailStats `json:"tables"`
}

// 表详细统计
type TableDetailStats struct {
	Name      string `json:"name"`
	Rows      int64  `json:"rows"`
	DataSize  string `json:"dataSize"`
	IndexSize string `json:"indexSize"`
	Engine    string `json:"engine"`
	Collation string `json:"collation"`
}

// ExecuteQuery 执行SQL查询
func ExecuteQuery(c *gin.Context) {
	var req struct {
		SQL string `json:"sql" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.PARAM_ERROR, "SQL语句不能为空")
		return
	}

	sql := strings.TrimSpace(req.SQL)

	// 记录开始时间
	startTime := time.Now()

	// 执行查询
	rows, err := models.Db.Raw(sql).Rows()
	if err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("查询失败: %v", err))
		return
	}
	defer rows.Close()

	// 获取列名
	columns, err := rows.Columns()
	if err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("获取列信息失败: %v", err))
		return
	}

	// 读取数据
	var result []map[string]interface{}
	for rows.Next() {
		// 创建接收数据的切片
		values := make([]interface{}, len(columns))
		valuePtrs := make([]interface{}, len(columns))
		for i := range values {
			valuePtrs[i] = &values[i]
		}

		if err := rows.Scan(valuePtrs...); err != nil {
			response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("读取数据失败: %v", err))
			return
		}

		// 构建结果map
		row := make(map[string]interface{})
		for i, col := range columns {
			val := values[i]
			// 处理[]byte类型
			if b, ok := val.([]byte); ok {
				row[col] = string(b)
			} else if t, ok := val.(time.Time); ok {
				// 处理时间类型，转换为"2006-01-02 15:04:05"格式
				row[col] = t.Format("2006-01-02 15:04:05")
			} else {
				row[col] = val
			}
		}
		result = append(result, row)
	}

	// 计算执行时间
	executeTime := time.Since(startTime).Milliseconds()

	queryResult := QueryResult{
		Columns:     columns,
		Rows:        result,
		RowCount:    len(result),
		ExecuteTime: executeTime,
	}

	response.ResponseOK(c, queryResult)
}

// GetTableList 获取数据库表列表
func GetTableList(c *gin.Context) {
	var tables []string
	rows, err := models.Db.Raw("SHOW TABLES").Rows()
	if err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("获取表列表失败: %v", err))
		return
	}
	defer rows.Close()

	for rows.Next() {
		var tableName string
		if err := rows.Scan(&tableName); err != nil {
			continue
		}
		tables = append(tables, tableName)
	}

	response.ResponseOK(c, tables)
}

// GetTableStructure 获取表结构
func GetTableStructure(c *gin.Context) {
	tableName := c.Query("tableName")
	if tableName == "" {
		response.ResponseErrorWithMsg(c, HttpCode.PARAM_ERROR, "表名不能为空")
		return
	}

	// 防止SQL注入
	if strings.Contains(tableName, " ") || strings.Contains(tableName, ";") {
		response.ResponseErrorWithMsg(c, HttpCode.PARAM_ERROR, "无效的表名")
		return
	}

	var structure []TableStructure
	// 使用SHOW FULL COLUMNS获取包含注释的完整字段信息
	sql := fmt.Sprintf("SHOW FULL COLUMNS FROM `%s`", tableName)

	if err := models.Db.Raw(sql).Scan(&structure).Error; err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("获取表结构失败: %v", err))
		return
	}

	response.ResponseOK(c, structure)
}

// GetDatabaseStats 获取数据库统计信息
func GetDatabaseStats(c *gin.Context) {
	// 获取当前数据库名
	var dbName string
	if err := models.Db.Raw("SELECT DATABASE()").Scan(&dbName).Error; err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("获取数据库名失败: %v", err))
		return
	}

	// 获取表统计信息
	var tableStats []TableDetailStats
	sql := `
		SELECT 
			TABLE_NAME as name,
			TABLE_ROWS as rows,
			CONCAT(ROUND(DATA_LENGTH / 1024 / 1024, 2), ' MB') as data_size,
			CONCAT(ROUND(INDEX_LENGTH / 1024 / 1024, 2), ' MB') as index_size,
			ENGINE as engine,
			TABLE_COLLATION as collation
		FROM information_schema.TABLES 
		WHERE TABLE_SCHEMA = ?
		ORDER BY DATA_LENGTH DESC
	`

	if err := models.Db.Raw(sql, dbName).Scan(&tableStats).Error; err != nil {
		response.ResponseErrorWithMsg(c, HttpCode.FAILURE, fmt.Sprintf("获取统计信息失败: %v", err))
		return
	}

	// 计算总计
	var totalRows int64
	var totalDataLength, totalIndexLength float64

	detailSQL := `
		SELECT 
			SUM(TABLE_ROWS) as total_rows,
			SUM(DATA_LENGTH) as total_data_length,
			SUM(INDEX_LENGTH) as total_index_length
		FROM information_schema.TABLES 
		WHERE TABLE_SCHEMA = ?
	`

	var stats struct {
		TotalRows        int64   `json:"total_rows"`
		TotalDataLength  float64 `json:"total_data_length"`
		TotalIndexLength float64 `json:"total_index_length"`
	}

	if err := models.Db.Raw(detailSQL, dbName).Scan(&stats).Error; err == nil {
		totalRows = stats.TotalRows
		totalDataLength = stats.TotalDataLength
		totalIndexLength = stats.TotalIndexLength
	}

	result := DatabaseStats{
		TableCount:   len(tableStats),
		TotalRows:    totalRows,
		DatabaseSize: fmt.Sprintf("%.2f MB", totalDataLength/1024/1024),
		IndexSize:    fmt.Sprintf("%.2f MB", totalIndexLength/1024/1024),
		Tables:       tableStats,
	}

	response.ResponseOK(c, result)
}
